﻿using Heroius.Extension;
using Heroius.Extension.Desktop;
using Heroius.Extension.WPF;
using Heroius.Files;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

namespace IEPI.BIATranscribe
{
    /// <summary>
    /// 主上下文实体
    /// </summary>
    public class Project : ObservableEntity
    {
        /// <summary>
        /// 主上下文实体
        /// </summary>
        public Project()
        {
            DocPages = new ObservableCollection<PageInfo>();
            DocPages.Add(new PageInfo() { Code = 1 });

            OddPageDef = new GridPageDef()
            {
                GridPageMargin_Left = Properties.Settings.Default.OddMarginLeft,
                GridPageMargin_Top = Properties.Settings.Default.OddMarginTop,
                GridPageMargin_Right = Properties.Settings.Default.OddMarginRight,
                GridPageMargin_Bottom = 0,
                RowCount = Properties.Settings.Default.OddRowCount,
                ColumnCount = Properties.Settings.Default.OddColCount,
                RowHeight = Properties.Settings.Default.OddRowHeight,
                ColumnWidths = Properties.Settings.Default.OddColWidths
            };
            EvenPageDef = new GridPageDef()
            {
                GridPageMargin_Left = Properties.Settings.Default.EvenMarginLeft,
                GridPageMargin_Top = Properties.Settings.Default.EvenMarginTop,
                GridPageMargin_Right = Properties.Settings.Default.EvenMarginRight,
                GridPageMargin_Bottom = 0,
                RowCount = Properties.Settings.Default.EvenRowCount,
                ColumnCount = Properties.Settings.Default.EvenColCount,
                RowHeight = Properties.Settings.Default.EvenRowHeight,
                ColumnWidths = Properties.Settings.Default.EvenColWidths
            };
        }

        #region 文档文件系统

        /// <summary>
        /// 文档页面图像所在相对目录，与<see cref="ObsTargetPath"/>互为冗余
        /// </summary>
        [EntitySilo]
        public string TargetPath { get { return _TargetPath; } set { _TargetPath = value; RaisePropertyChangedEvent("TargetPath"); } }
        string _TargetPath = "";
        /// <summary>
        /// 文档页面图像所在绝对目录，与<see cref="TargetPath"/>互为冗余
        /// </summary>
        [EntitySilo]
        public string ObsTargetPath { get { return _ObsTargetPath; } set { _ObsTargetPath = value; RaisePropertyChangedEvent("ObsTargetPath"); } }
        string _ObsTargetPath = "";

        /// <summary>
        /// 运行时有效绝对路径，根据<see cref="TargetPath"/>及<see cref="ObsTargetPath"/>冗余进行有效性筛选后得到的值
        /// </summary>
        public string EffectTargetPath { get { return _EffectTargetPath; } set {
                _EffectTargetPath = value; RaisePropertyChangedEvent("EffectTargetPath");
            } }
        string _EffectTargetPath = "";

        /// <summary>
        /// 对<see cref="EffectTargetPath"/>中文件名内容捕获
        /// </summary>
        [EntitySilo, PropertyPanel(MatchKey = "proj", Label = "正则捕获格式")]
        public string RegexpPattern { get { return _RegexpPattern; } set { _RegexpPattern = value; RaisePropertyChangedEvent("RegexpPattern"); } }
        string _RegexpPattern = Properties.Settings.Default.DocFilePattern;
        /// <summary>
        /// 经由<see cref="RegexpPattern"/> 捕获的索引
        /// </summary>
        [EntitySilo, PropertyPanel(MatchKey = "proj", Label = "页面排序依据捕获索引")]
        public int PageCodeIndex { get { return _PageCodeIndex; } set { _PageCodeIndex = value; RaisePropertyChangedEvent("PageCodeIndex"); } }
        int _PageCodeIndex = Properties.Settings.Default.DocOrderCatchIdx;

        /// <summary>
        /// 文档页面集合
        /// </summary>
        [EntitySilo]
        public ObservableCollection<PageInfo> DocPages { get { return _DocPages; } set { _DocPages = value; RaisePropertyChangedEvent("DocPages"); } }
        ObservableCollection<PageInfo> _DocPages;

        /// <summary>
        /// 在获取有效路径后，更新文档集合
        /// </summary>
        public void LoadFrom(ProjectViewModel model)
        {
            if (model != null)
            {
                ObsTargetPath = model.EffectTargetPath;
                TargetPath = PathHelper.ObsoleteToRelative(model.EffectTargetPath + '/', App.RootPath + '/');
                EffectTargetPath = model.EffectTargetPath;
                RegexpPattern = model.RegexpPattern;
                PageCodeIndex = model.PageCodeIndex;
            }
            DocPages.Clear();
            var dir = new DirectoryInfo(EffectTargetPath);
            if (dir.Exists)
            {
                var files = dir.GetFiles();
                Regex reg = new Regex(RegexpPattern);
                List<PageInfo> templist = new List<PageInfo>();
                foreach (var file in files)
                {
                    var m = reg.Match(file.Name);
                    if (m.Success)
                    {
                        templist.Add(new PageInfo()
                        {
                            Trans = new ImageTransInfo()
                            {
                                FileName = file.Name
                            },
                            Code = (m.Groups.Count > PageCodeIndex) ? m.Groups[PageCodeIndex].Value.As<int>(0) : 0
                        });
                    }
                }
                if (templist.Count > 0)
                {
                    //make sure following the page code and from 1
                    var odred = templist.OrderBy(item => item.Code);
                    var expcode = odred.First().Code - 1;
                    foreach (var item in odred)
                    {
                        item.Code -= expcode;
                        DocPages.Add(item);
                    }
                }
            }
        }
        /// <summary>
        /// 检查并移除不存在的文档页
        /// </summary>
        public void Validate()
        {
            for (int i = DocPages.Count - 1; i >= 0; i--)
            {
                if (!File.Exists(GetImageFullPath(DocPages[i].Trans.FileName))) DocPages.RemoveAt(i);
            }
        }

        string GetImageFullPath(string transFileName)
        {
            return $"{EffectTargetPath}/{transFileName}";
        }

        #endregion

        #region 表格定义

        /// <summary>
        /// 奇数页表格定义
        /// </summary>
        [EntitySilo]
        public GridPageDef OddPageDef { get { return _OddPageDef; } set { _OddPageDef = value; RaisePropertyChangedEvent("OddPageDef"); } }
        GridPageDef _OddPageDef;
        /// <summary>
        /// 偶数页表格定义
        /// </summary>
        [EntitySilo]
        public GridPageDef EvenPageDef { get { return _EvenPageDef; } set { _EvenPageDef = value; RaisePropertyChangedEvent("EvenPageDef"); } }
        GridPageDef _EvenPageDef;

        #endregion

        #region 表格导出

        /// <summary>
        /// 输出表格顶部文本
        /// </summary>
        [EntitySilo]
        public string HeadText { get { return _HeadText; } set { _HeadText = value; RaisePropertyChangedEvent("HeadText"); } }
        string _HeadText = "";
        /// <summary>
        /// 区分奇偶页
        /// </summary>
        [EntitySilo]
        public bool TellOE { get { return _TellOE; } set { _TellOE = value; RaisePropertyChangedEvent("TellOE"); } }
        bool _TellOE = true;
        /// <summary>
        /// 导出列定义，由列标记依序排列，半角逗号分隔
        /// </summary>
        [EntitySilo]
        public string ColumnDef { get { return _ColumnDef; } set { _ColumnDef = value; RaisePropertyChangedEvent("ColumnDef"); } }
        string _ColumnDef = "O0,E0";

        #endregion
    }

    /// <summary>
    /// 主上下文实体 在UI中可编辑的视图模型
    /// </summary>
    public class ProjectViewModel: ObservableEntity
    {
        /// <summary>
        /// 运行时有效绝对路径 - UI影子，仅用于UI绑定
        /// </summary>
        [PropertyPanel(MatchKey = "proj", Label = "目标文件夹", ToolTip = "浏览到保存有待拓写图片的目录"), DataType("Folder")]
        public string EffectTargetPath
        {
            get { return _EffectTargetPath; }
            set
            {
                _EffectTargetPath = value; RaisePropertyChangedEvent("EffectTargetPath");
            }
        }
        string _EffectTargetPath = "";

        /// <summary>
        /// 对<see cref="EffectTargetPath"/>中文件名内容捕获
        /// </summary>
        [EntitySilo, PropertyPanel(MatchKey = "proj", Label = "正则捕获格式")]
        public string RegexpPattern { get { return _RegexpPattern; } set { _RegexpPattern = value; RaisePropertyChangedEvent("RegexpPattern"); } }
        string _RegexpPattern = Properties.Settings.Default.DocFilePattern;
        /// <summary>
        /// 经由<see cref="RegexpPattern"/> 捕获的索引
        /// </summary>
        [EntitySilo, PropertyPanel(MatchKey = "proj", Label = "页面排序依据捕获索引")]
        public int PageCodeIndex { get { return _PageCodeIndex; } set { _PageCodeIndex = value; RaisePropertyChangedEvent("PageCodeIndex"); } }
        int _PageCodeIndex = Properties.Settings.Default.DocOrderCatchIdx;

        /// <summary>
        /// 从 project 更新界面要素
        /// </summary>
        /// <param name="project"></param>
        public void LoadFrom(Project project)
        {
            EffectTargetPath = project.EffectTargetPath;
            RegexpPattern = project.RegexpPattern;
            PageCodeIndex = project.PageCodeIndex;
        }
    }
}
